#pragma once

#include <iostream>
#include <sys/select.h>
#include <string>
#include <functional>
#include <sys/epoll.h>
#include "err.hpp"
#include "Sock.hpp"

using namespace std;
static const int defaultfd = -1; // 默认fd
static const int size = 128;     //
class Epoller
{
public:
    Epoller(int fd = defaultfd) : _epfd(fd) {}
    ~Epoller()
    {
        if (_epfd != defaultfd)
        {
            close(_epfd);
        }
    }
    void Create()
    {
        logMessage(DEBUG, "enter epoller create");
        _epfd = epoll_create(size); // 将管理事件数传进去，创建一个具有指定事件数的epoll模型
        if (_epfd < 0)
        {
            logMessage(ERROR, "epoll_create error");
            exit(ERROR_EPOLL_CREATE);
        }
        logMessage(DEBUG, "out epoller create,_epfd: %d\n", _epfd);
    }
    // 用户告知内核，需要底层监管那些事件
    bool Add_Event(int sock, uint16_t event) // 将sock和event添加到epoll模型中
    {
        struct epoll_event epv;
        epv.events = event;
        epv.data.fd = sock;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sock, &epv);
        return n == 0;
    }
    // 内核告诉用户，已经就绪了多少个事件
    int Wait(struct epoll_event revent[], int num, int timeout) // 监管num个事件，就绪事件保存在revent数组中
    {
        logMessage(DEBUG, "enter epoll_Wait");

        int n = epoll_wait(_epfd, revent, num, timeout);
        logMessage(DEBUG, "quit epoll_Wait,get n: %d", n);
   //     sleep(2);
        return n; // 内核帮助用户监管事件，返回已经就绪的事件数量
    }

    bool Control(int sock, uint32_t event, int action)
    {
        struct epoll_event epv;
        epv.events = event;
        epv.data.fd = sock;
        int n = 0;
        if (action == EPOLL_CTL_MOD)
        {
            logMessage(NORMAL,"enter Control MOD");
            n = epoll_ctl(_epfd, action, sock, &epv);
        }
        else if (action == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, action, sock, nullptr);
        }
        else
            n = -1;

        return n == 0;
    }
    void Close()
    {
        if (_epfd != defaultfd)
        {
            close(_epfd);
        }
    }

private:
    int _epfd;
};